package judesart.app.client.ui.pub.exhibition;

import java.util.ArrayList;
import java.util.List;

import judesart.app.client.controller.ExhibitionController;
import judesart.app.client.controller.ExhibitionControllerAsync;
import judesart.app.client.ui.pub.layout.PublicMainLayout;
import judesart.app.domain.Address;
import judesart.app.domain.Exhibition;
import judesart.app.domain.ExhibitionArtwork;
import judesart.app.domain.ExhibitionPhoto;
import judesart.app.domain.ExhibitionVideo;
import pl.rmalinowski.gwt2swf.client.ui.SWFWidget;

import com.allen_sauer.gwt.log.client.Log;
import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ListLoader;
import com.extjs.gxt.ui.client.data.MemoryProxy;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.Composite;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.Html;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.ListView;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.ColumnData;
import com.extjs.gxt.ui.client.widget.layout.ColumnLayout;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.TabLayoutPanel;

public class PubExhibitionDetailPanel extends Composite {

    private static final DateTimeFormat formater = DateTimeFormat.getFormat("EEE, MMMM dd, yyyy");

    private final ExhibitionControllerAsync exhibitionController = ExhibitionController.Util.getInstance();
    private final LayoutContainer mainPanel;
    private final Html htmlTitle;
    private final Html htmlDates;
    private final Html htmlLocation;
    private final Html htmlDetail;
    private final Html htmlContext;
    private final ListView<BeanModel> listViewPhotos;
    private final List<ExhibitionPhoto> photos = new ArrayList<ExhibitionPhoto>();
    private final ListLoader<ListLoadResult<ExhibitionPhoto>> photosLoader;
    private final ListView<BeanModel> listViewArtworks;
    private final List<ExhibitionArtwork> artworks = new ArrayList<ExhibitionArtwork>();
    private final ListLoader<ListLoadResult<ExhibitionArtwork>> artworksLoader;
    private final TabLayoutPanel tabLayoutPanel;
    private final FlowPanel videosPanel;
    private Html htmlGalleryName;
    private Html htmlGalleryAddr1;
    private Html htmlGalleryAddr2;
    private Html htmlGalleryAddr3;
    private Dialog galleryAddressDiaglog;
    private Exhibition exhibition;

    private final FlowPanel photosPanel;

    private final FlowPanel artworksPanel;

	private LayoutContainer imagePanel;

    public PubExhibitionDetailPanel() {
        MemoryProxy<List<ExhibitionPhoto>> photosProxy = new MemoryProxy<List<ExhibitionPhoto>>(photos);
        photosLoader = new BaseListLoader<ListLoadResult<ExhibitionPhoto>>(photosProxy, new BeanModelReader());
        ListStore<BeanModel> photosStore = new ListStore<BeanModel>(photosLoader);

        MemoryProxy<List<ExhibitionArtwork>> artworksProxy = new MemoryProxy<List<ExhibitionArtwork>>(artworks);
        artworksLoader = new BaseListLoader<ListLoadResult<ExhibitionArtwork>>(artworksProxy, new BeanModelReader());
        ListStore<BeanModel> artworksStore = new ListStore<BeanModel>(artworksLoader);

        mainPanel = new LayoutContainer();
        mainPanel.setWidth(900);
        mainPanel.setStyleAttribute("min-height", "600px");
        mainPanel.setBorders(false);
        mainPanel.setId("id-jaw-PubExhibitionDetailPanel");
        mainPanel.setStyleAttribute("clear", "both");

        LayoutContainer leftPanel = new LayoutContainer();
        leftPanel.setId("id-jaw-PubExhibitionDetailPanel-left");
        leftPanel.setStyleAttribute("float", "left");
        leftPanel.setWidth(260);

        htmlTitle = new Html();
        htmlTitle.setTagName("h1");
        htmlTitle.setStyleName("title", true);
        leftPanel.add(htmlTitle);

        imagePanel = new LayoutContainer();
        imagePanel.setSize(200, 200);
        imagePanel.add(newImage("/images/empty_200x200.png"));
        leftPanel.add(imagePanel);

        htmlContext = new Html();
        htmlContext.setTagName("div");
        htmlContext.setId("id-jaw-PubExhibitionDetailPanel-context");
        leftPanel.add(htmlContext);

        mainPanel.add(leftPanel);

        LayoutContainer rightPanel = new LayoutContainer();
        rightPanel.setId("id-jaw-PubExhibitionDetailPanel-right");
        rightPanel.setStyleAttribute("float", "right");
        rightPanel.setWidth(594);

        htmlDates = new Html();
        htmlDates.setTagName("span");
        htmlDates.addStyleName("dates");
        rightPanel.add(htmlDates);
        htmlLocation = new Html();
        htmlLocation.setTagName("span");
        htmlLocation.addStyleName("location");
        rightPanel.add(htmlLocation);
        Anchor moreLink = new Anchor("(+info)");
        moreLink.addStyleName("small");
        moreLink.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                onAddressClick(event);
            }
        });
        rightPanel.add(moreLink);
        htmlDetail = new Html();
        htmlDetail.setTagName("span");
        htmlDetail.addStyleName("detail");
        rightPanel.add(htmlDetail);

        tabLayoutPanel = new TabLayoutPanel(4, Unit.EM);
        tabLayoutPanel.setSize("600px", "300px");
        rightPanel.add(tabLayoutPanel);

        listViewPhotos = createListView(photosStore,
                "id-jaw-PubExhibitionDetailPanel-photos-list");
        photosPanel = new FlowPanel();
        photosPanel.add(listViewPhotos);
        photosPanel.getElement().setId("id-jaw-mycontainer-photos");
        tabLayoutPanel.add(photosPanel, "Photos", false);

        videosPanel = new FlowPanel();
        videosPanel.getElement().setId("id-jaw-mycontainer-videos");
        tabLayoutPanel.add(videosPanel, "Videos", false);

        listViewArtworks = createListView(artworksStore,
                "id-jaw-PubExhibitionDetailPanel-artworks-list");
        artworksPanel = new FlowPanel();
        artworksPanel.add(listViewArtworks);
        artworksPanel.getElement().setId("id-jaw-mycontainer-artworks");
        tabLayoutPanel.add(artworksPanel, "Artworks", false);

        buildGalleryAddressDialog();

        mainPanel.add(rightPanel);

        initComponent(mainPanel);
    }

	private Image newImage(String url) {
		Image image = new Image(url);
        image.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                onImageClick(event);
            }
        });
        image.addStyleName("image");
        image.addStyleName("jaw-clickable");
		return image;
	}

    private void onImageClick(ClickEvent event) {
        Log.debug(" > onImageClick ");
        ExhibitionPhoto photo = exhibition.getPhotos().get(0);

        showImageDialog(photo.getImageId().toString(), null);
    }

    private void onAddressClick(ClickEvent event) {
        galleryAddressDiaglog.show();
    }

    private ListView<BeanModel> createListView(ListStore<BeanModel> store,
            String id) {
        ListView<BeanModel> listView = new ListView<BeanModel>(store) {
            @Override
            protected BeanModel prepareData(BeanModel model) {
                if (model.getBean() instanceof ExhibitionArtwork) {
                    model.set(
                            "imageId",
                            ((ExhibitionArtwork) model.getBean()).getMainImageId());
                    model.set(
                            "description",
                            ((ExhibitionArtwork) model.getBean()).getArtworkTitle());
                }
                return model;
            }
        };
        listView.setLoadingText("loading...");
        listView.setBorders(false);
        listView.addStyleName("thumb-list");
        listView.setTemplate(getTemplate());
        listView.setItemSelector("div.thumb-wrap");
        listView.getSelectionModel().addListener(Events.SelectionChange,
                new Listener<SelectionChangedEvent<BeanModel>>() {
                    public void handleEvent(SelectionChangedEvent<BeanModel> be) {
                        onSelectionChanged(be);
                    }
                });
        listView.setId(id);
        return listView;
    }

    public void open(final Long exhibitionId) {
        exhibitionController.getExhibition(exhibitionId,
                new AsyncCallback<Exhibition>() {

                    @Override
                    public void onSuccess(Exhibition result) {
                        show(result);
                        PublicMainLayout.getInstance().loading(false);
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                        Log.debug("Error opening exhibition [" + exhibitionId
                                + "]", caught);
                        PublicMainLayout.getInstance().loading(false);
                        History.back();
                    }
                });
    }

    private void show(Exhibition exhibition) {
        this.exhibition = exhibition;
        htmlTitle.setHtml(exhibition.getTitle());

        if (exhibition.getPhotos() != null && exhibition.getPhotos().size() > 0) {
            Long imageId = exhibition.getPhotos().get(0).getImageId();
            imagePanel.removeAll();
            imagePanel.add(newImage("/image/" + imageId + "_200x200"));
        }

        StringBuffer ctxBuff = new StringBuffer();
        if (exhibition.getCurator() != null
                && exhibition.getCurator().trim().length() > 0) {
            ctxBuff.append("<span class='curator'><span class='label'>Curated by </span>");
            ctxBuff.append(exhibition.getCurator());
            ctxBuff.append("</span>");
        }
        if (exhibition.getExhibitingArtists() != null
                && exhibition.getExhibitingArtists().size() > 0) {
            ctxBuff.append("<span class='artists'><span class='label'>Exhibiting also </span>");
            ctxBuff.append("<ul>");
            for (String artist : exhibition.getExhibitingArtists()) {
                ctxBuff.append("<li>").append(artist).append("</li>");
            }
            ctxBuff.append("</ul>");
            ctxBuff.append("</span>");
        }
        htmlContext.setHtml(ctxBuff.toString());

        StringBuffer buff = new StringBuffer();
        buff.append(formater.format(exhibition.getStartDate())).append(" - ").append(
                formater.format(exhibition.getEndDate()));
        htmlDates.setHtml(buff.toString());
        buff = new StringBuffer();
        buff.append(exhibition.getGalleryName());
        Address address = exhibition.getGalleryAddress();
        if (address != null && address.getCity() != null
                && address.getCity().trim().length() > 0
                && address.getCountry() != null) {
            buff.append(" - ").append(address.getCity()).append(", ").append(
                    address.getCountry().title());
        }
        htmlLocation.setHtml(buff.toString());
        htmlDetail.setHtml(exhibition.getDetail().getValue());

        htmlGalleryName.setHtml(exhibition.getGalleryName());
        if (address != null) {
            htmlGalleryAddr1.setHtml(address.getAddress1());
            htmlGalleryAddr2.setHtml(address.getPostalCode() + " "
                    + address.getCity());
            htmlGalleryAddr3.setHtml(address.getCountry().name());
        } else {
            htmlGalleryAddr1.setHtml("");
            htmlGalleryAddr2.setHtml("");
            htmlGalleryAddr3.setHtml("");
        }

        List<ExhibitionVideo> videos = exhibition.getVideos();
        videosPanel.clear();
        if (videos != null && videos.size() > 0) {
            tabLayoutPanel.getTabWidget(0).setVisible(true);
            for (ExhibitionVideo video : videos) {
                SWFWidget player = new SWFWidget("http://www.youtube.com/v/"
                        + video.getVideoId() + "?version=3", 400, 200);
                videosPanel.add(player);
            }
        }

        photos.clear();
        if (exhibition.getPhotos() != null && exhibition.getPhotos().size() > 1) {
            photos.addAll(exhibition.getPhotos().subList(1,
                    exhibition.getPhotos().size()));
        }
        photosLoader.load();

        artworks.clear();
        if (exhibition.getArtworks() != null
                && exhibition.getArtworks().size() > 0) {
            Log.debug(" -->> artworks [" + exhibition.getArtworks().size()
                    + "]");
            artworks.addAll(exhibition.getArtworks());
        }
        artworksLoader.load();
        mainPanel.layout();
    }

    private void onSelectionChanged(SelectionChangedEvent<BeanModel> be) {
        Object source = be.getSource();
        Log.debug("source [" + source + "]");
        if (be.getSelection().size() == 0) {
            return;
        }
        final BeanModel model = be.getSelection().get(0);
        if (model.getBean() instanceof ExhibitionArtwork) {
            History.newItem("gallery/artwork/"
                    + ((ExhibitionArtwork) model.getBean()).getArtworkId().toString());
        } else {
            showImageDialog(((Long) model.get("imageId")).toString(),
                    (String) model.get("description"));
        }
        listViewPhotos.getSelectionModel().deselectAll();
    }

    private void showImageDialog(String imageId, String description) {
        Dialog dialog = new Dialog();
        dialog.setSize(760, 600);
        dialog.setScrollMode(Scroll.AUTO);
        Image image = new Image("/image/" + imageId + "_745x500");
        dialog.add(image);
        if (description != null) {
            dialog.addText(description);
        }
        dialog.setBodyStyle("width: 100%; text-align: center; color: #999999;");
        dialog.setHideOnButtonClick(true);
        dialog.setButtons(Dialog.OK);
        dialog.show();
    }

    private void buildGalleryAddressDialog() {
        galleryAddressDiaglog = new Dialog();
        galleryAddressDiaglog.setSize(260, 200);
        galleryAddressDiaglog.setScrollMode(Scroll.AUTO);
        galleryAddressDiaglog.setBodyBorder(false);
        LayoutContainer lc = new LayoutContainer();
        lc.setId("id-jaw-PubExhibitionDetailPanel-address");
        htmlGalleryName = new Html();
        htmlGalleryName.setTagName("h2");
        lc.add(htmlGalleryName);
        htmlGalleryAddr1 = new Html();
        htmlGalleryAddr1.setTagName("div");
        lc.add(htmlGalleryAddr1);
        htmlGalleryAddr2 = new Html();
        htmlGalleryAddr2.setTagName("div");
        lc.add(htmlGalleryAddr2);
        htmlGalleryAddr3 = new Html();
        htmlGalleryAddr3.setTagName("div");
        lc.add(htmlGalleryAddr3);
        galleryAddressDiaglog.add(lc);
        galleryAddressDiaglog.getButtonBar().removeAll();
        Button btnClose = new Button("Close", new SelectionListener<ButtonEvent>() {
            @Override
            public void componentSelected(ButtonEvent ce) {
                galleryAddressDiaglog.hide();
            }
        });
        galleryAddressDiaglog.addButton(btnClose);
    }

    private native String getTemplate() /*-{
        return ['<tpl for=".">', 
        '<div class="thumb-wrap" id="id-jaw-image-{imageId}">', 
        '<div class="thumb"><img src="/image/{imageId}_75x75_crop"/></div>',
        '</div>',
        '</tpl>', 
        '<!-- div class="x-clear"></div -->'
        ].join("");
    }-*/;
}
